package com.yueqian.framework.filter;

import java.io.IOException;
import java.util.List;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import com.yueqian.framework.constants.CommonConstants;
import com.yueqian.framework.entity.LoginUser;
import com.yueqian.framework.utils.JwtUtils;
import com.yueqian.framework.utils.RedisUtils;
import com.yueqian.system.entity.User;
import com.yueqian.system.mapper.RoleMapper;

import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;


@Component
@RequiredArgsConstructor
@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {

	private final JwtUtils jwtProvider;

	private final RedisUtils redisUtils;

	private final RoleMapper roleMapper;


	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
		final String token = request.getHeader("Authorization");
		if (StrUtil.isBlank(token) || "undefined".equals(token)) {
			filterChain.doFilter(request, response);
			return;
		}
		try {
		final String userName = jwtProvider.extractUserName(token);
			//进行限流
			String key = "rate_limit:" + userName;
//			slidingWindowRateLimiter.allowRequest(userName);
			//锁续期
			if (StrUtil.isBlank(userName) || !redisUtils.renewKeysExpire(request,userName)) {
				return;
			}
			User user = redisUtils.getCacheObject(userName);
			LoginUser userDetails = LoginUser.builder().user(user).build();
			if (jwtProvider.isTokenValid(token, userDetails)) {
				List<String> roles = roleMapper.getRoleByUserId(user.getId());
				userDetails.setRoles(roles);
				SecurityContext context = SecurityContextHolder.createEmptyContext();
				UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
						userDetails, null, userDetails.getAuthorities());
				authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
				context.setAuthentication(authToken);
				SecurityContextHolder.setContext(context);
					// 将用户ID存到Request中, 在数据审计时用到
				request.setAttribute(CommonConstants.REQUEST_ATTRIBUTE_USER_ID, userDetails.getUser().getId());
			}
			filterChain.doFilter(request, response);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}
}
